package org.project.single.utils;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import org.project.single.pojo.constant.CacheNameConst;
import org.project.single.pojo.dto.dict.DictDataCacheDto;
import org.project.single.pojo.dto.dict.DictTypeCacheDto;
import org.project.single.pojo.po.SysDictData;
import org.project.single.pojo.po.SysDictType;
import org.project.single.service.SysDictService;
import org.redisson.api.RBucket;
import org.redisson.api.RMap;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.stone.project.baseCommon.pojo.dto.CommonKeyValue;
import org.stone.project.baseRedis.utils.CacheDbOptProxyUtil;
import org.stone.project.baseRedis.utils.RedisUtil;

import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 字典工具
 */
public class DictUtil {
    /**
     * 根据key和状态获取可用字典
     * 先取缓存，再取库
     * @param key
     * @return
     */
    public static List<DictDataCacheDto> getDictDataCacheByKey(String key) {
        return getDictDataCacheByKey(key,1);
    }


    /**
     * 根据key和状态获取字典
     * 先取缓存，再取库
     * @param key
     * @param enable
     */
    public static List<DictDataCacheDto> getDictDataCacheByKey(String key,Integer enable) {
        String redisKey = CacheNameConst.getCacheName(CacheNameConst.DICT_DATA_CACHE_DATA,key);

        //获取字典数据
        Stream<DictDataCacheDto> stream = CacheDbOptProxyUtil.cacheOrSelectDb(redisKey,()->{
            RMap<String, DictDataCacheDto> data = RedisUtil.getRMap(redisKey);
            return data.values();
        },findDictDataCacheDtoDbByCode(key),data->{
            SpringUtil.getBean(SysDictService.class).updateDictDataAllCache(key,(Collection<SysDictData>)data);
        }).stream();

        //条件过滤
        if(ObjectUtil.isNotNull(enable))
            stream = stream.filter(ele->{
                return ele.getEnableFlag().equals(enable);
            });
        return stream.sorted(Comparator.comparing(DictDataCacheDto::getSortNum,Comparator.nullsLast(Comparator.naturalOrder()))).collect(Collectors.toList());
    }

    /**
     * 获取可用字典类型
     * @param key
     * @return
     */
    public static DictTypeCacheDto getDictTypeCacheByKey(String key) {
        return getDictTypeCacheByKey(key,1);
    }

    /**
     * 获取字典类型
     * @param key
     * @return
     */
    public static DictTypeCacheDto getDictTypeCacheByKey(String key,Integer enable) {
        String redisKey = CacheNameConst.getCacheName(CacheNameConst.DICT_TYPE_CACHE_DATA, key);

        //获取字典类型
        DictTypeCacheDto dictTypeCacheDto = CacheDbOptProxyUtil.cacheOrSelectDb(key, () -> {
            RBucket<DictTypeCacheDto> rBucket = RedisUtil.getRBucket(redisKey);
            return rBucket.get();
        }, findDictTypeCacheDtoDbByCode(key), data -> {
            SpringUtil.getBean(SysDictService.class).updateDictTypeCache(1,key, data);
        });

        //条件过滤
        if (ObjectUtil.isNotNull(enable)){
            if (dictTypeCacheDto.getEnableFlag().equals(enable)){
                return dictTypeCacheDto;
            }else
                return null;
        }else{
            return dictTypeCacheDto;
        }
    }

    /**
     * 查询数据库字典类型对象
     * @param code
     * @return
     */
    public static Supplier<CommonKeyValue<DictTypeCacheDto,SysDictType>> findDictTypeCacheDtoDbByCode(String code){
        return ()->{
            CommonKeyValue commonKeyValue = new CommonKeyValue();
            SysDictType dictTypeCacheDtoDbByCode = SpringUtil.getBean(SysDictService.class).findDictTypeCacheDtoDbByCode(code);
            commonKeyValue.setKey(BeanUtil.copyProperties(dictTypeCacheDtoDbByCode,DictTypeCacheDto.class));
            commonKeyValue.setValue(dictTypeCacheDtoDbByCode);
            return commonKeyValue;
        };
    }


    /**
     * 查询数据库字典数据对象
     * @param code
     * @return
     */
    public static Supplier<CommonKeyValue<Collection<DictDataCacheDto>,Collection<SysDictData>>> findDictDataCacheDtoDbByCode(String code){
        return ()->{
            CommonKeyValue commonKeyValue = new CommonKeyValue();
            List<SysDictData> dictDataCacheDtoDbByCode = SpringUtil.getBean(SysDictService.class).findDictDataCacheDtoDbByCode(code);
            List<DictDataCacheDto> cacheData = dictDataCacheDtoDbByCode.stream()
                    .map(ele -> BeanUtil.copyProperties(ele, DictDataCacheDto.class))
                    .collect(Collectors.toList());
            commonKeyValue.setKey(cacheData);
            commonKeyValue.setValue(dictDataCacheDtoDbByCode);
            return commonKeyValue;
        };
    }
}
